/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package assisisw.smartcal.securitysubsystem;

import assisisw.smartcal.entitysubsystem.IUserController;
import assisisw.smartcal.entitysubsystem.User;
import assisisw.smartcal.entitysubsystem.exceptions.user.UserNotRegisteredException;
import assisisw.smartcal.utilities.CommunicationException;
import assisisw.smartcal.utilities.Utilities;
import java.util.Properties;
import java.util.regex.Pattern;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.mail.Authenticator;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

/**
 *
 * @author Francesco
 */
@Stateless
public class EMailVerifier implements IMailVerifier 
{

    // Instance Fields

    /***/
    @EJB
    private IUserController userController ;
    
    /***/
    private final String fromAddress = "ssmartcal@gmail.com" ;
    
    /***/
    private final String fromAddressPassword = "1smartcal9" ;
    
    /***/
    private final String tokenMessageSubject = "SmartCAl Account Activation" ;
    
    /***/
    private Pattern mailPattern ;
    
    /***/
    private Properties properties ;
    
    /***/
    private Authenticator mailAuthenticator ;
    
    // Instance Methods
    
    /***/
    public EMailVerifier () {}
  
    /***/
    @PostConstruct 
    public void init () 
    {
        mailPattern = Pattern.compile ( Utilities.EMAIL_REGEXP ) ;
        loadMailSenderProperties();
    }
    
    /**
     * @param mail 
     * @return
     */
    @Override
    public boolean isStaticallyOk ( String mail ) 
    {
        boolean res ;
        res = mailPattern.matcher ( mail ).matches () ;
        return res ;
    }
    
     /**
     * @param mail
     * @return 
     */
    @Override
    public boolean exists ( String mail ) 
    {
        /*
        InternetAddress internetAddress ;
        boolean res ;
        try 
        {
            internetAddress = new InternetAddress ( mail ) ;
            internetAddress.validate();
            res = true ;
        }
        catch (AddressException ex) 
        {
            res = false ;
        }
        return res ;*/
        return true ;
    }
    
    /**
     * @param eMail
     * @return
     * @throws CommunicationException
     */
    @Override
    public String sendToken ( String eMail ) throws CommunicationException
    {
        MimeMessage message ;
        Session session ;
        User u ;
        Multipart multipart ;
        BodyPart bodyPart ;
        String token ;
        TokenGenerator tokenGenerator ;
        try 
        {
            tokenGenerator = new TokenGenerator () ;
            session = Session.getDefaultInstance ( properties , mailAuthenticator ) ;
            message = new MimeMessage ( session ) ;
            message.setFrom ( new InternetAddress ( fromAddress ) ) ;
            bodyPart = new MimeBodyPart () ;
            multipart = new MimeMultipart () ;
            token = tokenGenerator.generateToken ( eMail ) ;
            bodyPart.setContent ( "Clicca il link qui sotto per attivare il tuo account SmartCAL !<br/><a href = \"http://localhost:8080/smartcal/tokenverifier?token="+token+"&mail="+eMail+"\">Attiva !</a>" , "text/html") ;
            multipart.addBodyPart ( bodyPart ) ; 
            message.addRecipient ( Message.RecipientType.TO , new InternetAddress ( eMail ) );
            message.setSubject ( tokenMessageSubject ) ;
            message.setContent ( multipart ) ;
            Transport.send ( message ) ; 
        } 
        catch ( AddressException ex ) 
        {
            throw new CommunicationException ( ex , ex.getMessage () ) ;
        } 
        catch (MessagingException ex) 
        {
            throw new CommunicationException ( ex , ex.getMessage () ) ;
        } 
        return token ;
    }
     
    /**
     * @param mail
     * @param token
     * @throws ActivationException
     */
    @Override
    public void verifyTokenAndActivate ( String mail , String token ) 
            throws ActivationException 
    {
        User u ;
        if ( userController.isRegistered ( mail ) )
        {
            try 
            {            
                u = userController.getUser ( mail );
                if ( ! u.isActive () )
                {
                    if ( u.getToken ().equals ( token ) )
                        userController.activate ( u ) ; 
                    else
                        throw new ActivationException ( null , "Token not correct." ) ;
                }
                else
                    throw new ActivationException ( null , "Account already active." ) ;    // can we provide a better feedback here than an error
            } 
            catch ( UserNotRegisteredException ex ) 
            {
                throw new ActivationException ( null , "Unknown Error" ) ;
            }
        }
        else
            throw new ActivationException ( null , "Trying to activate an non existent account" ) ;
    }
    
    private void loadMailSenderProperties ()
    {
        properties = new Properties () ;
        properties.put ( "mail.smtp.host" , "smtp.gmail.com") ;
        properties.put ( "mail.smtp.port" , "465" ) ;
        properties.put ( "mail.smtp.auth" , true ) ;
        properties.put ( "mail.smtp.starttls.enable", true ) ;
        properties.put ( "mail.smtp.ssl.enable", true ) ;
        mailAuthenticator = new MailSenderAuthenticator () ;
    }
    
    // Other Members
    
    /***/
    private class MailSenderAuthenticator extends Authenticator 
    {
    
        // Instance Fields
        
        /***/
        private PasswordAuthentication passwordAuthentication ;
        
        // Instance Methods
        
        protected MailSenderAuthenticator () 
        {
            super () ;
            passwordAuthentication = new PasswordAuthentication ( fromAddress , fromAddressPassword ) ;
        }
        
        /**
         * AS THE SUPER'S ONE.
         */
        @Override
        public PasswordAuthentication getPasswordAuthentication () 
        {
            return passwordAuthentication ;
        }
    
    }
    
}
